package ai.timefold.solver.spring.boot.it;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import ai.timefold.solver.core.config.solver.SolverConfig;
import ai.timefold.solver.core.impl.io.jaxb.SolverConfigIO;
import ai.timefold.solver.spring.boot.it.domain.IntegrationTestEntity;
import ai.timefold.solver.spring.boot.it.domain.IntegrationTestSolution;
import ai.timefold.solver.spring.boot.it.domain.IntegrationTestValue;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.io.Resource;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TimefoldSolverTestResourceIntegrationTest {

    @LocalServerPort
    String port;

    @Value("classpath:solver-full.xml")
    Resource exampleSolverConfigXml;

    @Test
    void testSolve() {
        WebTestClient client = WebTestClient.bindToServer()
                .baseUrl("http://localhost:" + port + "/integration-test")
                .build();

        var firstEntity = new IntegrationTestEntity("0");
        firstEntity.setValueList(List.of(new IntegrationTestValue("1"), new IntegrationTestValue("2")));
        var secondEntity = new IntegrationTestEntity("1");
        secondEntity.setValueList(List.of(new IntegrationTestValue("1"), new IntegrationTestValue("2")));
        var thirdEntity = new IntegrationTestEntity("2");
        thirdEntity.setValueList(List.of(new IntegrationTestValue("1"), new IntegrationTestValue("2")));
        IntegrationTestSolution problem = new IntegrationTestSolution(
                List.of(firstEntity, secondEntity, thirdEntity),
                List.of(new IntegrationTestValue("0")));
        client.post()
                .bodyValue(problem)
                .exchange()
                .expectBody()
                .jsonPath("score").isEqualTo("0")
                .jsonPath("entityList").isArray()
                .jsonPath("valueList").isArray()
                .jsonPath("entityList[0].id").isEqualTo("0")
                .jsonPath("entityList[0].value.id").isEqualTo("0")
                .jsonPath("entityList[1].id").isEqualTo("1")
                .jsonPath("entityList[1].value.id").isEqualTo("1")
                .jsonPath("entityList[2].id").isEqualTo("2")
                .jsonPath("entityList[2].value.id").isEqualTo("2");

    }

    @Test
    void testSolverXmlParsing() throws IOException {
        // Test to verify parsing a complex SolverConfig will work in native image.
        // XML file was generated by taking the XSD file available at
        // https://timefold.ai/xsd/solver and generating an XML file from it using
        // the "Tools > XML Actions > Generate XML Document from XML Schema..." action in IDEA
        SolverConfigIO solverConfigIO = new SolverConfigIO();
        SolverConfig solverConfig = solverConfigIO.read(new InputStreamReader(exampleSolverConfigXml.getInputStream()));
        assertThat(solverConfig).isNotNull();
        assertThat(solverConfig.getSolutionClass()).isEqualTo(Object.class);
        assertThat(solverConfig.getPhaseConfigList()).isNotEmpty();
    }
}
